package com.digua.base.base

import android.R
import android.app.Activity
import android.content.Context
import android.os.Build
import androidx.multidex.MultiDex
import androidx.multidex.MultiDexApplication
import com.blankj.utilcode.util.CrashUtils
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.Utils
import com.digua.base.config.BaseConfig.APP_SD_PATH
import com.digua.base.util.AuthorizeUtil
import com.digua.base.util.CacheUtils
import com.digua.base.util.LogUtil
import com.scwang.smart.refresh.footer.ClassicsFooter
import com.scwang.smart.refresh.header.MaterialHeader
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import com.umeng.analytics.MobclickAgent
import org.xutils.x
import java.io.File
import java.util.LinkedList
import kotlin.system.exitProcess


open class App : MultiDexApplication() {
    protected val mActivityList: MutableList<Activity> = LinkedList()
    protected var context: Context? = null

    init {
        //设置全局的Header构建器
        SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout ->
            layout.setPrimaryColorsId(R.color.white, R.color.black) //全局设置主题颜色
            // ClassicsHeader(context)//经典刷新头
            // BezierRadarHeader(context)//雷达刷新头
            // FalsifyHeader(context)//虚拟刷新头
            MaterialHeader(context)//谷歌刷新头
            //TwoLevelHeader(context)//谷歌刷新头
        }
        //设置全局的Footer构建器
        SmartRefreshLayout.setDefaultRefreshFooterCreator { context, _ ->
            //指定为经典Footer，默认是 BallPulseFooter
            ClassicsFooter(context).setDrawableSize(20f)//经典加载
            //BallPulseFooter(context)//球脉冲加载
            //FalsifyFooter(context)//虚拟加载
        }
    }

    companion object {
        val instance: App by lazy { Utils.getApp() as App }
        var authorize: AuthorizeUtil.Authorize? = null
    }

    override fun onCreate() {
        super.onCreate()
        context = this
        initCrash()
        x.Ext.init(this)
        x.Ext.setDebug(CacheUtils.isDebug()) // 是否输出debug日志, 开启debug会影响性能.
        closeAndroidPDialog()
        AuthorizeUtil.authorize { authorize = it }
        clearCache()
    }

    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        MultiDex.install(base)
    }

    override fun onLowMemory() {
        super.onLowMemory()
        System.gc()
    }

    /**
     * 适配Android P 报错:Detected problems with API compatibility
     */
    private fun closeAndroidPDialog() {
        try {
            val aClass = Class.forName("android.content.pm.PackageParser\$Package")
            val declaredConstructor = aClass.getDeclaredConstructor(String::class.java)
            declaredConstructor.isAccessible = true
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            try {
                val cls = Class.forName("android.app.ActivityThread")
                val declaredMethod = cls.getDeclaredMethod("currentActivityThread")
                declaredMethod.isAccessible = true
                val activityThread = declaredMethod.invoke(null)
                val fields = cls.declaredFields
                for (field in fields) {
                    if (field.name == "mHiddenApiWarningShown") {
                        val mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown")
                        mHiddenApiWarningShown.isAccessible = true
                        mHiddenApiWarningShown.setBoolean(activityThread, true)
                        break
                    }
                }
            } catch (e: Exception) {
                LogUtil.e("异常:", e)
            }
        }
    }

    private fun initCrash() {
        try {
            CrashUtils.init { crashInfo: CrashUtils.CrashInfo -> LogUtil.e("异常拦截：$crashInfo") }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun clearCache() {
        delDirFile(File(APP_SD_PATH, "files/crash"), 3)
    }

    /**
     * 删除目录下的文件
     * @param dir 要操作的文件夹
     * @param holdDay 要保留多少天以内的文件
     */
    private fun delDirFile(dir: File, holdDay: Int = 0) {
        if (!dir.exists()) return
        val time = holdDay * 24 * 60 * 60 * 1000
        dir.listFiles()?.let {
            for (file in it) {
                if (holdDay == 0 || System.currentTimeMillis() - file.lastModified() > time) {
                    FileUtils.delete(file)
                }
            }
        }
    }

    // add Activity
    fun addActivity(activity: Activity) {
        mActivityList.add(activity)
    }

    fun exit() {
        try {
            mActivityList.map { it.finish() }
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        } finally {
            MobclickAgent.onKillProcess(this)
            exitProcess(0)
        }
    }

    fun colse(clz: Class<*>) {
        val tempArr1 = mActivityList.filter { it::class.java.simpleName == clz.simpleName }
        val activity: Activity = tempArr1.firstOrNull() ?: return
        if (!activity.isFinishing) activity.finish()
        mActivityList.remove(activity)
    }

    fun <T> finishAll(clz: Class<T>) {
        mActivityList.forEach {
            if (it::class.java.simpleName != clz.simpleName) {
                if (!it.isFinishing) it.finish()
            }
        }
        mActivityList.removeIf { it::class.java.simpleName != clz.simpleName }
    }
}